package com.sise.Array;

/**
 *      剑指 Offer 29. 顺时针打印矩阵
 *      输入一个矩阵，按照从外向里以顺时针的顺序依次打印出每一个数字。
 *
 *      输入：matrix = [[1,2,3],[4,5,6],[7,8,9]]
 *      输出：[1,2,3,6,9,8,7,4,5]
 *
 *
 *
 *      //定义一个整型数组:3行4列      int a[][] = new int[3][4];
 *      //获取行数---3行             int lenY = a.length;   -   上下高度
 *      //获取列数---4列             int lenX = a[0].length;  -   左右长度
 */
public class _offer_29_spiralOrder {
    public static void main(String[] args) {
        int[][] matrix = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
        int[] ints = spiralOrder(matrix);
        for (int i = 0; i < ints.length; i++){
            System.out.print(ints[i]);
        }
    }

    static public int[] spiralOrder(int[][] matrix) {

        // 判断是否非空
        if (matrix.length == 0){
            return new int[0];
        }

        // 设置结果数组的长度，对于数组的增加不是使用 add，而是用 idx 作为下标递增
        int[] result = new int[matrix.length * matrix[0].length];
        int idx = 0;

        // 求出四条边的范围，根据此向内收缩
        int left = 0;
        int right = matrix[0].length - 1;
        // 注意：这里的 top 和 bottom 应该反过来，因为方阵左上角的坐标应该是[0][0]，而不是[3][0]，所以 top 的高度应该是 0，方便后续按照二维数组的下标遍历
        int top = 0;
        int bottom = matrix.length - 1;

        while (true){

            // 从左到右；如果将第一行走完了，故此将高度减一，如果 上边界减一后 小于下边界，那么就算是超出边界，退出
            for (int i = left; i <= right; i++){
                result[idx++] = matrix[top][i];
            }
            if (++top > bottom) break;

            // 从上向下，贴近右边界向下，走完 for 语句后将右边界 减一；因为已经走过了
            for (int i = top; i <= bottom; i++){
                result[idx++] = matrix[i][right];
            }
            if (--right < left) break;

            // 从右到左
            for (int i = right; i >= left; i--){
                result[idx++] = matrix[bottom][i];
            }
            if (--bottom < top) break;

            // 从小往上
            for (int i = bottom; i >= top; i--){
                result[idx++] = matrix[i][left];
            }
            if (++left > right) break;
        }
        return result;
    }
}
